export default class VariableChangeMonitor {
  /**
   * 初始化变量监控器
   * @param {number} duration - 监控时长（毫秒），变量超过此时长未变化则触发回调
   * @param {Function} callback - 超时回调函数，接收当前未变化的变量值作为参数
   * @param {Object} [options={}] - 配置项
   * @param {boolean} [options.continueMonitor=false] - 超时后是否继续监控（默认触发一次后停止）
   */
  constructor(duration, callback, options = {}) {
    this.duration = duration; // 监控超时时间（毫秒）
    this.callback = callback; // 超时回调函数
    this.options = { continueMonitor: false, ...options };

    this.lastValue = undefined; // 上次记录的变量值（深拷贝）
    this.timerId = null; // 计时器 ID
    this.isRunning = false; // 监控是否正在运行
  }

  /**
   * 启动监控（可选传入初始变量值）
   * @param {*} [initialValue] - 初始变量值（若有则直接开始计时）
   */
  startMonitor(initialValue) {
    this.isRunning = true;
    if (initialValue !== undefined) {
      this.lastValue = this._deepClone(initialValue);
      this._restartTimer();
    }
  }

  /**
   * 停止监控，清除计时器
   */
  stopMonitor() {
    this.isRunning = false;
    this._clearTimer();
    this.lastValue = undefined;
  }

  /**
   * 更新变量值（核心方法）
   * - 变量变化：重置计时器，重新开始计时
   * - 变量未变：不操作
   * @param {*} currentValue - 当前变量值
   */
  updateValue(currentValue) {
    if (!this.isRunning) {
      throw new Error("监控未启动，请先调用 startMonitor()");
    }

    const currentValueClone = this._deepClone(currentValue);
    // 首次更新或变量值变化时，重置计时
    if (this.lastValue === undefined || !this._deepEqual(currentValueClone, this.lastValue)) {
      this.lastValue = currentValueClone;
      this._restartTimer();
    }
  }

  /**
   * 重启计时器（清除旧计时器，启动新计时器）
   */
  _restartTimer() {
    this._clearTimer();
    // 启动新计时器，超时后触发回调
    this.timerId = setTimeout(() => this._timerCallback(), this.duration);
  }

  /**
   * 清除当前计时器
   */
  _clearTimer() {
    if (this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
  }

  /**
   * 计时器超时回调
   */
  _timerCallback() {
    if (this.isRunning && this.lastValue !== undefined) {
      this.callback(this.lastValue); // 触发用户自定义回调
      // 若未配置持续监控，超时后停止监控
      if (!this.options.continueMonitor) {
        this.stopMonitor();
      } else {
        // 持续监控：超时后重新启动计时器（继续监控下一个周期）
        this._restartTimer();
      }
    }
  }

  /**
   * 深拷贝（处理基础类型、对象、数组、日期、正则等）
   * @param {*} value - 待拷贝的值
   * @returns {*} 拷贝后的值
   */
  _deepClone(value) {
    // 基础类型直接返回
    if (value === null || typeof value !== "object") {
      return value;
    }

    // 日期类型
    if (value instanceof Date) {
      return new Date(value);
    }

    // 正则类型
    if (value instanceof RegExp) {
      return new RegExp(value.source, value.flags);
    }

    // 数组类型
    if (value instanceof Array) {
      return value.map(item => this._deepClone(item));
    }

    // 对象类型（排除 null 和其他对象子类）
    const cloneObj = {};
    Object.keys(value).forEach(key => {
      cloneObj[key] = this._deepClone(value[key]);
    });
    return cloneObj;
  }

  /**
   * 深比较（判断两个值是否完全相等）
   * @param {*} a - 比较值1
   * @param {*} b - 比较值2
   * @returns {boolean} 是否相等
   */
  _deepEqual(a, b) {
    // 基础类型直接比较
    if (a === b) {
      return true;
    }

    // 均为对象且不为 null
    if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
      // 日期比较
      if (a instanceof Date && b instanceof Date) {
        return a.getTime() === b.getTime();
      }

      // 正则比较
      if (a instanceof RegExp && b instanceof RegExp) {
        return a.source === b.source && a.flags === b.flags;
      }

      // 数组比较（长度 + 每个元素）
      if (a instanceof Array && b instanceof Array) {
        if (a.length !== b.length) return false;
        for (let i = 0; i < a.length; i++) {
          if (!this._deepEqual(a[i], b[i])) return false;
        }
        return true;
      }

      // 对象比较（键名 + 键值）
      const keysA = Object.keys(a);
      const keysB = Object.keys(b);
      if (keysA.length !== keysB.length) return false;
      for (const key of keysA) {
        if (!keysB.includes(key) || !this._deepEqual(a[key], b[key])) return false;
      }
      return true;
    }

    // 其他情况（如一个是对象一个是基础类型）
    return false;
  }
}